package com.hangxintong.common.base.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

import java.util.concurrent.TimeUnit;

/**
 * @Auther: tsj
 * @Date: 2021/2/26 09:59
 * @Description: redis锁操作
 */
@Service
public class LockService {

    private static Logger log = LoggerFactory.getLogger(LockService.class);
    private static final String LOCK_SUCCESS = "OK";

    @Autowired
    private RedisTemplate redisTemplate;

    public void unLock(String key){
        redisTemplate.delete(key);
    }

    public synchronized boolean isLock(String key,int seconds){
        /**
         * 存储数据到缓存中，并制定过期时间和当Key存在时是否覆盖。
         * nxxx的值只能取NX或者XX，如果取NX，则只有当key不存在是才进行set，如果取XX，则只有当key已经存在时才进行set
         * expx的值只能取EX或者PX，代表数据过期时间的单位，EX代表秒，PX代表毫秒。
         * time 过期时间，单位是expx所代表的单位。
         */
        return (boolean) redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {
//                 Jedis nativeConnection = (Jedis) redisConnection.getNativeConnection();
//                 String result = nativeConnection.set(key, "1", "NX", "EX", seconds);

                 Boolean aBoolean = redisTemplate.hasKey(key);
                 if (!aBoolean){
                     redisTemplate.opsForValue().set(key,"1",seconds, TimeUnit.SECONDS);
                     return true;
                 }


//                return result!=null && result.equalsIgnoreCase(LOCK_SUCCESS) ;
                return false;
            }
        });
    }


//    public void unLock(String key, String value) {
//
//    }
//
//    public <T> T lockExecute(String key, LockExecute<T> lockExecute) {
//        boolean isLock = isLock(key, 5);
//        final int SLEEP_TIME = 100;
//        final int RETRY_NUM = 60;
//        int i;
//        for (i = 0; i < RETRY_NUM; i++) {
//            if (isLock) {
//                break;
//            }
//            try {
//                log.debug("wait redis lock key > {}", key);
//                Thread.sleep(SLEEP_TIME);
//            } catch (InterruptedException e) {
//                log.warn("wait redis error {}", e.getMessage());
//            }
//            isLock = isLock(key, 5);
//        }
//        if (!isLock) {
//            log.warn("wait lock time out key > {}", key);
//            return lockExecute.waitTimeOut();
//        }
//        try {
//            if (i > 0) {
//                log.debug("wait lock retry count {}", i);
//            }
//            return lockExecute.execute();
//        } finally {
//            unLock(key);
//        }
//    }
}
